package com.xiaoshuidi.cloud.framework.sms.core.client.impl.yunpian;

import cn.hutool.core.net.URLEncodeUtil;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.xiaoshuidi.cloud.framework.common.core.KeyValue;
import com.xiaoshuidi.cloud.framework.common.exception.ErrorCode;
import com.xiaoshuidi.cloud.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.xiaoshuidi.cloud.framework.common.util.json.JsonUtils;
import com.xiaoshuidi.cloud.framework.sms.core.client.SmsCommonResult;
import com.xiaoshuidi.cloud.framework.sms.core.client.dto.SmsReceiveRespDTO;
import com.xiaoshuidi.cloud.framework.sms.core.client.dto.SmsSendRespDTO;
import com.xiaoshuidi.cloud.framework.sms.core.client.dto.SmsTemplateRespDTO;
import com.xiaoshuidi.cloud.framework.sms.core.client.impl.AbstractSmsClient;
import com.xiaoshuidi.cloud.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
import com.xiaoshuidi.cloud.framework.sms.core.property.SmsChannelProperties;
import okhttp3.*;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.time.Duration;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 云片短信
 */
public class YunpianSmsClient extends AbstractSmsClient {
    protected OkHttpClient okHttpClient;

    @Override
    protected void doInit() {
        okHttpClient = new OkHttpClient.Builder()
                .connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES))
                .connectTimeout(Duration.ofMinutes(1))
                .readTimeout(Duration.ofMinutes(1))
                .writeTimeout(Duration.ofMinutes(1))
                .hostnameVerifier((hostname, session) -> true)
                .build();
    }

    public YunpianSmsClient(SmsChannelProperties properties) {
        super(properties, new YunpianSmsCodeMapping());
    }

    @Override
    protected SmsCommonResult<SmsSendRespDTO> doSendSms(Long sendLogId, String mobile, String content,
                                                        String apiTemplateId, List<KeyValue<String, Object>> templateParams,
                                                        Set<String> shortUrlParams) throws Throwable {
        if (!CollectionUtils.isEmpty(shortUrlParams) && templateParams != null) {
            for (KeyValue<String, Object> url : templateParams) {
                if (shortUrlParams.contains(url.getKey())) {
                    ObjectNode result = call("/v2/short_url/shorten.json", "long_url=" + url.getValue());
                    ErrorCode errorCode = codeMapping.apply(JsonUtils.asText(result.get("code")));
                    if (errorCode.equals(GlobalErrorCodeConstants.SUCCESS)) {
                        String shortUrl = JsonUtils.asText(result.get("short_url"), "short_url");
                        if (StringUtils.hasText(shortUrl)) {
                            url.setValue(shortUrl);
                        }
                    }
                }
            }
        }
//        ObjectNode n = call("/v2/sms/single_send.json", String.format("mobile=%s&text=%s", mobile, URLEncodeUtil.encode(content)));
        ObjectNode n = tplSend(sendLogId, mobile, content, apiTemplateId, templateParams);
        return SmsCommonResult.build(n.get("code").asText(), n.get("msg").asText() + JsonUtils.asTextOrDefault(n.get("detail"), ""), sendLogId.toString(),
                new SmsSendRespDTO().setSerialNo(JsonUtils.asText(n.get("sid"))), codeMapping);
    }

    private ObjectNode tplSend(Long sendLogId, String mobile, String content,
                               String apiTemplateId, List<KeyValue<String, Object>> templateParams) throws IOException {
        StringBuilder b = new StringBuilder();
        b.append("mobile=").append(mobile).append("&tpl_id=").append(apiTemplateId)
                .append("&tpl_value=");
        if (templateParams != null && !CollectionUtils.isEmpty(templateParams)) {
            StringBuilder tplValue = new StringBuilder();
            for (KeyValue<String, Object> t : templateParams) {
                tplValue.append("%26").append(URLEncodeUtil.encode("#" + t.getKey() + "#"))
                        .append("=").append(URLEncodeUtil.encode(t.getValue().toString()));
            }
            b.append(tplValue.substring(3));
        }
        b.append("&uid=").append(sendLogId.toString());
        return call("/v2/sms/tpl_single_send.json", b.toString());
    }

    @Override
    protected List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable {
        return null;
    }

    @Override
    protected SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) throws Throwable {
        ObjectNode n = call("/v2/tpl/get.json", "tpl_id=" + apiTemplateId);

        return SmsCommonResult.build("0", "", null, new SmsTemplateRespDTO()
                .setId(n.get("tpl_id").asText())
                .setContent(n.get("tpl_content").asText())
                .setAuditStatus(SmsTemplateAuditStatusEnum.valueOf(n.get("check_status").asText()).getStatus())
                .setAuditReason(JsonUtils.asText(n.get("reason"))), codeMapping);
    }

    private ObjectNode call(String uri, String body) throws IOException {
        Request req = new Request.Builder()
                .url("https://sms.yunpian.com" + uri)
                .post(RequestBody.create("apikey=" + properties.getApiKey() + "&" + body,
                        MediaType.get("application/x-www-form-urlencoded;charset=utf-8")))
                .header("Accept", "application/json;charset=utf-8")
                .build();
        Response response = okHttpClient.newCall(req).execute();
        return JsonUtils.parseObject(response.body().bytes(), ObjectNode.class);
    }
}
